package com.town.garden.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.town.garden.chain.AbstractServerStartHandler;
import com.town.garden.constant.GlobalConstant;
import com.town.garden.entiy.ChannelInfo;
import com.town.garden.entiy.response.SearchIpcListInfoResponse;
import com.town.garden.enums.NVRApiEnum;
import com.town.garden.propertites.NvrProperties;
import com.town.garden.service.NvrIpcListInfoService;
import com.town.garden.storage.NvrSessionStorage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/5/13
 */
@Service(NvrIpcListInfoServiceImpl.BEAN_NAME)
@Slf4j
public class NvrIpcListInfoServiceImpl extends AbstractServerStartHandler implements NvrIpcListInfoService, Runnable {
    public static final String BEAN_NAME = "nvrIpcListInfoServiceImpl";
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private NvrProperties nvrProperties;
    @Autowired
    private ScheduledExecutorService scheduledExecutorService;
    /**
     * 控制初始化完成在调用下一个责任链
     */
    private final static CountDownLatch COUNT_DOWN_LATCH =new CountDownLatch(1);
    /**
     * 下一个责任链对象
     * {@linkplain ZLMediaKitServiceImpl}
     */
    @Autowired
    @Qualifier(ZLMediaKitServiceImpl.BEAN_NAME)
    private AbstractServerStartHandler abstractServerStartHandler;

    @Override
    public ResponseEntity<SearchIpcListInfoResponse> searchIpcListInfo() {
        //拼接请求url
        final String url = GlobalConstant.HTTPS_PREFIX + nvrProperties.getNvrServerIp() + NVRApiEnum.CHANNEL_INFO.getUrl();
        final HttpEntity<?> entity = new HttpEntity<>(null, NvrSessionStorage.headers);
        try {
            return restTemplate.exchange(url, HttpMethod.POST, entity, SearchIpcListInfoResponse.class);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void handlerOperation() {
        //启动定时任务查询ipc详情列表
        ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(this, 0, nvrProperties.getSearchSystemInfoTime(), TimeUnit.SECONDS);
        try {
            COUNT_DOWN_LATCH.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //执行下一个责任链
        abstractServerStartHandler.handlerOperation();
    }

    @Override
    public void run() {
        ResponseEntity<SearchIpcListInfoResponse> searchIpcListInfoResponseResponseEntity = searchIpcListInfo();
        if (Objects.nonNull(searchIpcListInfoResponseResponseEntity) && HttpStatus.OK.equals(searchIpcListInfoResponseResponseEntity.getStatusCode())) {
            initAndUpdateIPCInfo(searchIpcListInfoResponseResponseEntity.getBody());
            COUNT_DOWN_LATCH.countDown();
            //log.info("search ipcListInfo response is :{}", JSONUtil.parse(searchIpcListInfoResponseResponseEntity.getBody()));
        }
    }

    /**
     * 初始化Ipc信息存储集合和更新
     *
     * @param searchIpcListInfoResponse
     */
    private void initAndUpdateIPCInfo(SearchIpcListInfoResponse searchIpcListInfoResponse) {
        if (Objects.nonNull(searchIpcListInfoResponse) &&
                Objects.nonNull(searchIpcListInfoResponse.getData()) &&
                Objects.nonNull(searchIpcListInfoResponse.getData().getChannelInfo()) &&
                CollectionUtil.isNotEmpty(searchIpcListInfoResponse.getData().getChannelInfo())
        ) {
            Map<String, ChannelInfo> channelInfo = searchIpcListInfoResponse.getData().getChannelInfo();
            for (String key : channelInfo.keySet()
            ) {
                ChannelInfo channelInfoData = channelInfo.get(key);
                if (StrUtil.isNotEmpty(channelInfoData.getStatus())) {
                    NvrSessionStorage.CHANNEL_IP_MAP.put(key, channelInfoData);
                }
            }
        }
    }
}
